package com.swak.fx.support;

import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

import com.swak.fx.support.ui.UIController;
import com.swak.reactivex.threads.OrderContext.OrderAbleContext;
import com.swak.reactivex.threads.TimerContext;
import com.swak.reactivex.threads.TimerContext.ScheduledTimerTask;
import com.swak.ui.EventListener;
import com.swak.ui.Events;

/**
 * AbstractPage.
 * 
 * @author 618lf
 */
public abstract class AbstractPage extends AbstractView implements Lifecycle, UIController {

	protected final CompletableFuture<Void> initFuture = new CompletableFuture<>();
	protected final CompletableFuture<Void> closeFuture = new CompletableFuture<>();

	protected final Store $store;
	final OrderAbleContext $context;
	final TimerContext $timer;

	public AbstractPage() {

		// 存储
		this.$store = Store.New();

		// 执行力
		this.$timer = FxContexts.New().getTimerContext();
		this.$context = FxContexts.New().getWorkerContext().newOrderAbleContext();

		// 注入事件
		if (this instanceof EventListener) {
			Events.register(this);
		}
	}

	@Override
	public void setupValueChangedListeners() {
		super.setupValueChangedListeners();
	}

	@Override
	public void initializeFinish() {
		super.initializeFinish();
		this.initFuture.complete(null);
	}

	public CompletableFuture<Void> waitClose() {
		if (!this.closeFuture.isDone() && !this.closeFuture.isCancelled()
				&& !this.closeFuture.isCompletedExceptionally()) {
			closeFuture.complete(null);
		}
		return initFuture.thenCompose((v) -> {
			return closeFuture;
		});
	}

	public CompletableFuture<Void> whenInited() {
		return this.initFuture;
	}

	public CompletableFuture<Void> whenClosed() {
		return this.closeFuture;
	}

	@Override
	public void destory() {
		super.destory();
		try {
			Events.unregister(this);
		} catch (Exception e) {
		}
		try {
			this.tree.destory();
		} catch (Exception e) {
		}
		try {
			if (!this.closeFuture.isDone() && !this.closeFuture.isCancelled()
					&& !this.closeFuture.isCompletedExceptionally()) {
				this.closeFuture.complete(null);
			}
		} catch (Exception e) {
		}
		try {
			this.$context.shutdownNow();
		} catch (Exception e) {
		}
	}

	// ================================================================================
	// 状态变化
	// ================================================================================
	@Override
	public void windowStateChange(int state) {
		super.windowStateChange(state);
		if (!this.tree.pages.isEmpty()) {
			Stream<Lifecycle> pages = this.tree.stream();
			pages.forEach(page -> {
				if (page != null) {
					page.windowStateChange(state);
				}
			});
		}
	}

	@Override
	public void fireActivated() {
		if (this.root.isVisible()) {
			this.activated();
			if (!this.tree.pages.isEmpty()) {
				Stream<Lifecycle> pages = this.tree.stream();
				pages.forEach(page -> {
					if (page != null) {
						page.fireActivated();
					}
				});
			}
		}
	}

	@Override
	public void fireDeactivated() {
		this.deactivated();
		if (!this.tree.pages.isEmpty()) {
			Stream<Lifecycle> pages = this.tree.stream();
			pages.forEach(page -> {
				if (page != null) {
					page.fireDeactivated();
				}
			});
		}
	}

	// ================================================================================
	// Worker
	// ================================================================================
	@Override
	protected void $run(Runnable task) {
		this.$context.execute(task);
	}

	// ================================================================================
	// Timer
	// ================================================================================
	@Override
	protected ScheduledTimerTask $setTimeOut(Runnable task, long delayMs) {
		return this.$timer.schedule(() -> this.$context.execute(task), delayMs, TimeUnit.MILLISECONDS);
	}

	@Override
	protected ScheduledTimerTask $setTimeInterval(Runnable task, long period) {
		return this.$timer.scheduleAtFixedRate(() -> this.$context.execute(task), period, TimeUnit.MILLISECONDS);
	}

	// ================================================================================
	// Create Child Page (子页面)
	// ================================================================================
	final Parent tree = new Parent();

	protected <T extends AbstractPage> T NewPage(Class<T> pageClass) {
		return this.tree.NewPage(pageClass);
	}

	@SuppressWarnings("rawtypes")
	protected synchronized <T extends AbstractPage> T NewPage(Class<T> pageClass, boolean singleton, Class[] cs,
			Object[] ps) throws InstantiationException, IllegalAccessException, IllegalArgumentException,
			InvocationTargetException, SecurityException, NoSuchMethodException {
		return this.tree.NewPage(pageClass, singleton, cs, ps);
	}

	// ================================================================================
	// Create Comp (组件)
	// ================================================================================

	public <T extends AbstractComp> T NewComp(Class<T> theClass) {
		return this.tree.NewComp(theClass, this);
	}

	// ================================================================================
	// DestoryPage Comp (组件)
	// ================================================================================

	// 注意：可以不调用此方法来维护 tree 中 pages
	protected void DestoryPage(Lifecycle lifecycle) {
		this.tree.destory(lifecycle);
	}
}